/*
 * Copyright (C) 2019 ByteDance Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bytedance.scene.animation.interaction.progressanimation;

import com.bytedance.scene.animation.interaction.evaluator.FloatEvaluator;
import com.bytedance.scene.animation.interaction.evaluator.IntEvaluator;
import com.bytedance.scene.animation.interaction.evaluator.RectEvaluator;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.utils.Contour;
import ohos.agp.utils.Rect;
import ohos.utils.ObjectAttribute;

import java.util.HashMap;
import java.util.Set;

public class ViewOtherAnimationBuilder<T> extends ViewAnimationBuilder<T> {
    private static final ObjectAttribute<Component, Rect> CLIP = new ObjectAttribute<Component, Rect>(Rect.class, "clip") {
        @Override
        public void set(Component object, Rect value) {
        }

        @Override
        public Rect get(Component object) {
            return new Rect();
        }
    };

    private static final ObjectAttribute<Component, Float> BOUNDS_RADIUS = new ObjectAttribute<Component, Float>(Float.class, "bounds_radius") {
        private final Contour outline = new Contour();

        @Override
        public void set(Component object, final Float value) {
        }

        @Override
        public Float get(Component object) {
            return outline.getRadius();
        }
    };

    private static final ObjectAttribute<Component, Integer> SCROLL_X = new ObjectAttribute<Component, Integer>(Integer.class, "scroll_x") {
        @Override
        public void set(Component object, final Integer value) {
            object.scrollTo(value, object.getScrollValue(Component.AXIS_Y));
        }

        @Override
        public Integer get(Component object) {
            return object.getScrollValue(Component.AXIS_X);
        }
    };

    private static final ObjectAttribute<Component, Integer> SCROLL_Y = new ObjectAttribute<Component, Integer>(Integer.class, "scroll_y") {
        @Override
        public void set(Component object, final Integer value) {
            object.scrollTo(object.getScrollValue(Component.AXIS_X), value);
        }

        @Override
        public Integer get(Component object) {
            return object.getScrollValue(Component.AXIS_Y);
        }
    };

    private static final ObjectAttribute<Component, Rect> BOUNDS = new ObjectAttribute<Component, Rect>(Rect.class, "bounds") {
        @Override
        public void set(Component object, final Rect value) {
            object.setLeft(value.left);
            object.setTop(value.top);
            object.setRight(value.right);
            object.setBottom(value.bottom);
        }

        @Override
        public Rect get(Component object) {
            return new Rect();
        }
    };

    private HashMap<ObjectAttribute, Holder> hashMap = new HashMap<>();

    ViewOtherAnimationBuilder(Component view) {
        super(view);
    }


    public T clip(Rect fromValue, Rect toValue) {
        hashMap.put(CLIP, new Holder(new RectEvaluator(), fromValue, toValue));
        return (T) this;
    }

    public T clip(Rect value) {
        return (T) this;
    }

    public T boundsRadius(float toValue) {
        Contour outline = new Contour();
        float radius = outline.getRadius();
        return boundsRadius(radius, toValue);
    }

    public T boundsRadius(float fromValue, float toValue) {
        hashMap.put(BOUNDS_RADIUS, new Holder(new FloatEvaluator(), fromValue, toValue));
        return (T) this;
    }

    public T boundsRadiusBy(float deltaValue) {
        Contour outline = new Contour();
        float radius = outline.getRadius();
        return boundsRadius(radius, radius + deltaValue);
    }

    public T bounds(Rect fromValue, Rect toValue) {
        hashMap.put(BOUNDS, new Holder(new RectEvaluator(), fromValue, toValue));
        return (T) this;
    }

    public T bounds(Rect toValue) {
        Rect rect = new Rect();
        return bounds(rect, toValue);
    }

    public T scrollX(int fromValue, int toValue) {
        hashMap.put(SCROLL_X, new Holder(new IntEvaluator(), fromValue, toValue));
        return (T) this;
    }

    public T scrollX(int toValue) {
        return scrollX(mView.getScrollValue(Component.AXIS_X), toValue);
    }

    public T scrollXBy(int deltaValue) {
        return scrollX(mView.getScrollValue(Component.AXIS_X), mView.getScrollValue(Component.AXIS_X) + deltaValue);
    }

    public T scrollY(int fromValue, int toValue) {
        hashMap.put(SCROLL_Y, new Holder(new IntEvaluator(), fromValue, toValue));
        return (T) this;
    }

    public T scrollY(int toValue) {
        return scrollY(mView.getScrollValue(Component.AXIS_Y), toValue);
    }

    public T scrollYBy(int deltaValue) {
        return scrollY(mView.getScrollValue(Component.AXIS_Y), mView.getScrollValue(Component.AXIS_Y) + deltaValue);
    }

    @Override
    protected void onProgress(float progress) {
        super.onProgress(progress);

        Set<ObjectAttribute> set = hashMap.keySet();
        for (ObjectAttribute property : set) {
            Holder value = hashMap.get(property);
            property.set(mView, value.typeEvaluator.evaluate(progress, value.fromValue, value.toValue));
        }
    }
}
